home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / genass.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  21KB  |  731 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7.  *  GENASS.C
  8.  *
  9.  *    Assignment operators
  10.  */
  11.  
  12. /*
  13. **      $Filename: genass.c $
  14. **      $Author: dice $
  15. **      $Revision: 30.326 $
  16. **      $Date: 1995/12/24 06:09:40 $
  17. **      $Log: genass.c,v $
  18.  * Revision 30.326  1995/12/24  06:09:40  dice
  19.  * .
  20.  *
  21.  * Revision 30.154  1995/01/09  13:19:15  dice
  22.  * added check for illegal assignment with constant on lhs
  23.  *
  24.  * Revision 30.5  1994/06/13  18:37:28  dice
  25.  * byte ordering portability
  26.  *
  27.  * Revision 30.0  1994/06/10  18:04:51  dice
  28.  * .
  29.  *
  30.  * Revision 1.4  1993/11/22  00:28:36  jtoebes
  31.  * Final cleanup to eliminate all cerror() messages with strings.
  32.  *
  33.  * Revision 1.3  1993/04/10  17:14:00  jtoebes
  34.  * Inplemented static initialization of bitfields in structures.
  35.  *
  36. **/
  37.  
  38. #include "defs.h"
  39.  
  40. Prototype void GenEq(Exp **);
  41. Prototype void GenBracEq(Exp **);
  42. Prototype void GenBracedAssign(Exp **);
  43. Prototype void GenPercentEq(Exp **);
  44. Prototype void GenAndEq(Exp **);
  45. Prototype void GenStarEq(Exp **);
  46. Prototype void GenMiEq(Exp **);
  47. Prototype void GenDivEq(Exp **);
  48. Prototype void GenLtLtEq(Exp **);
  49. Prototype void GenGtGtEq(Exp **);
  50. Prototype void GenPlEq(Exp **);
  51. Prototype void GenOrEq(Exp **);
  52. Prototype void GenCaratEq(Exp **);
  53.  
  54. Prototype void GenAssEq(Exp **);
  55. Prototype void GenSpecialAssignment(Exp **, void (*)(Exp **));
  56.           void PadStructure(int, long *);
  57.  
  58. /*
  59.  *  Note: to change propogation to rhs, the lhs must still be propogated
  60.  *  when bitfields are involved.  Also what about &(a = 4); ?
  61.  */
  62.  
  63. void
  64. GenEq(pexp)
  65. Exp **pexp;
  66. {
  67.     Exp *exp = *pexp;
  68.     Exp *e1;
  69.     Exp *e2;
  70.  
  71.     if (GenPass == 0) {
  72. #ifdef NOTDEF    /* future opt */
  73.     e1 = exp->ex_ExpL;
  74.     if (e1->ex_Token == TokPreDec)
  75.         exp->ex_Flags |= EF_ASSPREDEC;
  76.     if (e1->ex_Token == TokPosInc)
  77.         exp->ex_Flags |= EF_ASSPOSINC;
  78. #endif
  79.     exp->ex_ExpL->ex_Flags |= EF_LHSASSIGN;
  80.  
  81.     CallLeft();
  82.  
  83.     if (exp->ex_ExpL->ex_Token == TokVarRef)
  84.         exp->ex_ExpL->ex_Var->RegFlags |= RF_MODIFIED;
  85.  
  86.     /*
  87.      *  Presetting the type is an optimization that is not required.
  88.      *  example:    char a, b; a = ~b; so ~b is done w/ chars.
  89.      */
  90.  
  91.     if (exp->ex_ExpR->ex_Type == NULL)
  92.         exp->ex_ExpR->ex_Type = exp->ex_ExpL->ex_Type;
  93.  
  94.     CallRight();
  95.     AssignRules(exp);
  96.     exp->ex_Flags |= EF_CRES;
  97.     exp->ex_Flags |= (exp->ex_ExpL->ex_Flags | exp->ex_ExpR->ex_Flags) & EF_CALL;
  98.     } else {
  99.     e2 = exp->ex_ExpR;
  100.  
  101.     /*
  102.      * a[i] = a[j] = a[k] = ... x;    must to rhs first or would build
  103.      * up scratch regs
  104.      */
  105.  
  106.     exp->ex_ExpL->ex_Flags |= EF_LHSASSIGN;
  107.  
  108.     if (e2->ex_Flags & (EF_ASSEQ|EF_CRES)) {
  109.         CallRight();
  110.         EnsureReturnStorageRight();
  111.         CallLeft();
  112.         e1 = exp->ex_ExpL;
  113.         e2 = exp->ex_ExpR;
  114.     } else {
  115.         CallLeft();
  116.         EnsureReturnStorageLeft();
  117.         e1 = exp->ex_ExpL;
  118.         e2 = exp->ex_ExpR;
  119.         if (e1->ex_Type->Id != TID_BITFIELD && (e2->ex_Flags & EF_CRES) == 0) {
  120.         e2->ex_Stor = e1->ex_Stor;
  121.         e2->ex_Flags |= EF_PRES;
  122.         }
  123.         CallRight();
  124.     }
  125.  
  126.     e1 = exp->ex_ExpL;
  127.     e2 = exp->ex_ExpR;
  128.  
  129.     if (e1->ex_Type->Id == TID_BITFIELD) {
  130.         e2 = exp->ex_ExpR;
  131.         asm_bfsto(exp, &e2->ex_Stor, &e1->ex_Stor);
  132.         FreeStorage(&e2->ex_Stor);
  133.     } else if (e2->ex_Flags & (EF_CRES|EF_ASSEQ)) {
  134.         e2 = exp->ex_ExpR;
  135.         asm_move(exp, &e2->ex_Stor, &e1->ex_Stor);
  136.         if (e1->ex_Stor.st_Type < ST_Reg && e1->ex_Stor.st_Type != ST_PtrConst)
  137.         yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  138.         FreeStorage(&e2->ex_Stor);
  139.     }
  140.     FreeStorage(&e1->ex_Stor);
  141.     if ((exp->ex_Flags & EF_RNU) == 0)
  142.         ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
  143.     }
  144. }
  145.  
  146. /*
  147.  *  Generate a braced assignment.  This is a two step process.    Step 1
  148.  *  copies static data to the local variable, Step 2 generates additonal
  149.  *  code to handle variable expressions.
  150.  */
  151.  
  152. void
  153. GenBracEq(pexp)
  154. Exp **pexp;
  155. {
  156.     Exp *exp = *pexp;
  157.  
  158.     if (GenPass == 0) {
  159.     exp->ex_ExpL->ex_Flags |= EF_LHSASSIGN;
  160.     CallLeft();
  161.     CallRight();
  162.     } else {
  163.     Stor t;
  164.     Stor ss;
  165.  
  166.     /*
  167.      *  process lhs, obtain effective address, then sequence
  168.      *  the storage structure according to the type
  169.      */
  170.  
  171.     CallLeft();
  172.     asm_getlea(exp, &exp->ex_ExpL->ex_Stor, &t);
  173.     exp->ex_ExpR->ex_Stor = t;
  174.     AutoAggregateBeg(&ss, exp->ex_ExpL->ex_Type);
  175.     t.st_Flags &= ~SF_LEA;    /*  XXX hack    */
  176.     t.st_Size = exp->ex_ExpL->ex_Type->Size;
  177.     asm_move(exp, &ss, &t);
  178.     CallRight();
  179.     AutoAggregateEnd();
  180.     }
  181. }
  182.  
  183. void PadStructure(size, bfhold)
  184. int size;
  185. long *bfhold;
  186. {
  187.    if (size > 4)
  188.    {
  189.     AutoAggregate(bfhold, 4);
  190.     AutoAggregate(NULL, size-4);
  191.    }
  192.    else
  193.    {
  194.     AutoAggregate(bfhold, size);
  195.    }
  196.    *bfhold = 0;
  197. }
  198.  
  199. /*
  200.  *  Generate a braced assignment.   Essentially run through the structure
  201.  *  generated by GCompBracedAssign() generating code for non-constant
  202.  *  objects and building a table for constant objects.
  203.  *
  204.  *  Each TokExpAssBlock already has an ex_Type assigned to it, for pass 2
  205.  *  storage is tracked for auto's
  206.  *
  207.  *  A TokExpAssBlock expression node may contain a linked list of
  208.  *  constants before it's nominal linked list of expressions.  This
  209.  *  hack was introduced to save massive amounts of space for large
  210.  *  static-initialized arrays.
  211.  */
  212.  
  213. void
  214. GenBracedAssign(pexp)
  215. Exp **pexp;
  216. {
  217.     Exp *exp = *pexp;
  218.  
  219.     if (GenPass == 0)
  220.     {
  221.     Type *type = exp->ex_Type;
  222.     long index = 0;
  223.  
  224.     Assert(type);
  225.  
  226.     if (exp->ex_ConstAry) {
  227.         long *captr;
  228.  
  229.         for (captr = exp->ex_ConstAry; captr; captr = (long *)captr[0], ++index) {
  230.         ;
  231.         }
  232.     }
  233.     if (exp->ex_ExpL) {
  234.         Exp **pnext;
  235.  
  236.         for (pnext = &exp->ex_ExpL; (exp = *pnext) != NULL; pnext = &exp->ex_Next, ++index) {
  237.         Type *actType;
  238.         Exp *nextExp = exp->ex_Next;
  239.  
  240.         if (exp->ex_Token == TokExpAssBlock) {
  241.             CallCenter();
  242.         } else {
  243.             if (type->Id == TID_ARY)
  244.             actType = type->SubType;
  245.             else if (type->Id == TID_STRUCT)
  246.             actType = type->Vars[index]->Type;
  247.             else if (type->Id == TID_UNION)
  248.             actType = type->Vars[0]->Type;
  249.             else
  250.             actType = type;
  251.  
  252.            /*
  253.             *  type usually refers to the parent type, e.g. ary
  254.             *  actType refers to the data type, e.g. int
  255.             */
  256.  
  257.  
  258.             if (exp->ex_Type == NULL)
  259.             exp->ex_Type = actType;
  260.  
  261.                     /* Check the type to ensure that it is compatible with what */
  262.                     /* they are asking for.  The only exception is when we are  */
  263.                     /* assigning a strings constant to an array of bytes.  This */
  264.                     /* is just one of those funny cases that C allows through   */
  265.             if (exp->ex_Token != TokStrConst ||
  266.                 type->Id != TID_ARY ||
  267.                 actType->Size != 1)
  268.             {
  269.             CallCenter();
  270.                         InitRules(&exp, actType);
  271.             }
  272.             exp->ex_Next = nextExp;
  273.             *pnext = exp;
  274.         }
  275.         }
  276.     }
  277.     } else {
  278.  
  279.     Type *type = exp->ex_Type;
  280.     Type *actType;
  281.     Exp *nextExp;
  282.     Stor t;
  283.     Stor c;
  284.     long index = 0;     /*    index, per char for string, else struct/union */
  285.     long baseOffset;    /*    bytes accumulated as we go    */
  286.     long bfhold = 0;    /*  Used to accumulate bitfield initializations   */
  287.     Exp **next;
  288.  
  289.     /*
  290.      *  When generating global data we track just the laid-down bytes.
  291.      *  When generating local auto-aggregate data we track both the
  292.      *  laid-down constants (bytes)
  293.      */
  294.  
  295.     Assert(type);
  296.  
  297.     if (GenGlobal == 0)
  298.         t = exp->ex_Stor;        /*  base base offset (real offset)  */
  299.  
  300.     baseOffset = 0;         /*  relative offset            */
  301.  
  302.     if (exp->ex_ConstAry) {
  303.         long *captr;
  304.  
  305.         for (captr = exp->ex_ConstAry; captr; captr = (long *)captr[0], ++index) {
  306.         if (type->Id == TID_ARY)
  307.             actType = type->SubType;
  308.         else if (type->Id == TID_STRUCT)
  309.             actType = type->Vars[index]->Type;
  310.         else if (type->Id == TID_UNION)
  311.             actType = type->Vars[0]->Type;
  312.         else
  313.             actType = type;
  314.         Assert(actType);
  315.  
  316.         if (type->Id == TID_STRUCT) {
  317.             long offset = type->Vars[index]->var_Stor.st_Offset;
  318.             if (offset > baseOffset) {
  319.             PadStructure(offset - baseOffset, &bfhold);
  320.             baseOffset = offset;
  321.             }
  322.         }
  323.  
  324.         if (actType->Id == TID_BITFIELD)
  325.         {
  326.             long offset = INT_SIZE * 8;
  327.             if (type->Id == TID_STRUCT)
  328.                 offset = type->Vars[index]->u.BOffset;
  329.             else if (type->Id != TID_INT)
  330.             yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  331.  
  332.                     bfhold |= (captr[1] & ((1 << actType->Size) - 1)) << offset;
  333.             /* We don't have the fix baseOffset because we are just */
  334.             /* a bitfield and may be putting more into the bitfield */
  335.             /* We instead rely upon the structure alignment code to */
  336.             /* Adjust the offset and flush out the bitfield that we */
  337.             /* have gathered.                                       */
  338.         }
  339.         else
  340.         {
  341.             /* If we have any bitfield residuals, we need to get it */
  342.             /* to be popped out.                                    */
  343.             switch(actType->Size)
  344.             {
  345.             case 0:
  346.             break;
  347.             case 1:
  348.             {
  349.                 char c = captr[1];
  350.                 AutoAggregate(&c, 1);
  351.             }
  352.             break;
  353.             case 2:
  354.             {
  355.                 short c = ToMsbOrderShort(captr[1]);
  356.                 AutoAggregate(&c, 2);
  357.             }
  358.             break;
  359.             case 4:
  360.             {
  361.                 long c = ToMsbOrder(captr[1]);
  362.                 AutoAggregate(&c, 4);
  363.             }
  364.             break;
  365.             default:
  366.             Assert(0);
  367.             break;
  368.             }
  369.  
  370.             baseOffset += actType->Size;
  371.         }
  372.         }
  373.     }
  374.     for (next = &exp->ex_ExpL; (exp = *next) != NULL; next = &exp->ex_Next, ++index) {
  375.         nextExp = exp->ex_Next;
  376.         if (type->Id == TID_ARY)
  377.         actType = type->SubType;
  378.         else if (type->Id == TID_STRUCT)
  379.         actType = type->Vars[index]->Type;
  380.         else if (type->Id == TID_UNION)
  381.             actType = type->Vars[0]->Type;
  382.         else
  383.         actType = type;
  384.         Assert(actType);
  385.  
  386.         /*
  387.          *    Determine starting alignment -- applies to structures
  388.          */
  389.  
  390.         if (type->Id == TID_STRUCT) {
  391.         long offset = type->Vars[index]->var_Stor.st_Offset;
  392.         if (offset > baseOffset) {
  393.             PadStructure(offset - baseOffset, &bfhold);
  394.             baseOffset = offset;
  395.         }
  396.         }
  397.  
  398.         if (exp->ex_Token == TokExpAssBlock) {
  399.         /*
  400.          *  Propogate real offset down
  401.          */
  402.  
  403.         if (GenGlobal == 0) {
  404.             exp->ex_Stor = t;
  405.             exp->ex_Stor.st_Offset += baseOffset;
  406.         }
  407.  
  408.         CallCenter();
  409.  
  410.         baseOffset += actType->Size;
  411.         } else {
  412.  
  413.         /*
  414.          *  string constants are a special case.  They are forced
  415.          *  into their own subblock since the index represents
  416.          *  the byte index rather then a structure field index
  417.          */
  418.  
  419.         if (exp->ex_Token == TokStrConst && type->Id == TID_ARY && actType->Size == 1) {
  420.             long offset = exp->ex_StrLen;
  421.             AutoAggregate(exp->ex_StrConst, offset);
  422.  
  423.             baseOffset += offset;
  424.             index += offset - 1;
  425.         } else {
  426.             CallCenter();
  427.             *next = exp;
  428.             exp->ex_Next = nextExp;
  429.  
  430.             /*
  431.              *    If constant then lay it out in the static portion of
  432.              *    the initialization routine, else lay out 0 in the
  433.              *    static portion and generate code.
  434.              */
  435.  
  436.             if (actType->Id == TID_BITFIELD)
  437.             {
  438.             long offset = INT_SIZE * 8;
  439.             long val    = 0;
  440.  
  441.             if (exp->ex_Stor.st_Type == ST_IntConst)
  442.                 val = exp->ex_Stor.st_IntConst;
  443.             else
  444.                 yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  445.  
  446.             if (type->Id == TID_STRUCT)
  447.                 offset = type->Vars[index]->u.BOffset;
  448.             else if (type->Id != TID_INT)
  449.                 yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  450.  
  451.             bfhold |= (val & ((1 << actType->Size) - 1)) << offset;
  452.  
  453.                 /* We don't have the fix baseOffset because we are just */
  454.                 /* a bitfield and may be putting more into the bitfield */
  455.                 /* We instead rely upon the structure alignment code to */
  456.                 /* Adjust the offset and flush out the bitfield that we */
  457.                 /* have gathered.                                       */
  458.             }
  459.             else
  460.             {
  461.  
  462.                         switch(exp->ex_Stor.st_Type) {
  463.                         case ST_IntConst:
  464.                             switch(actType->Size) {
  465.                 case 0:
  466.                                 break;
  467.                             case 1:
  468.                                 {
  469.                                     char c = exp->ex_Stor.st_IntConst;
  470.                                     AutoAggregate(&c, 1);
  471.                                 }
  472.                                 break;
  473.                             case 2:
  474.                                 {
  475.                                     short c = ToMsbOrderShort(exp->ex_Stor.st_IntConst);
  476.                                     AutoAggregate(&c, 2);
  477.                                 }
  478.                                 break;
  479.                             case 4:
  480.                                 {
  481.                                     long c = ToMsbOrder(exp->ex_Stor.st_IntConst);
  482.                                     AutoAggregate(&c, 4);
  483.                                 }
  484.                                 break;
  485.                             default:
  486.                                 Assert(0);
  487.                                 break;
  488.                             }
  489.                             break;
  490.                         case ST_FltConst:
  491.                             {
  492.                                 long ary[4];
  493.  
  494.                                 asm_fltconst(exp, &exp->ex_Stor, ary);
  495.                                 AutoAggregate(ary, exp->ex_Stor.st_Size);
  496.                             }
  497.                             break;
  498.                         case ST_RelLabel:
  499.                         case ST_RelName:
  500.                             if (GenGlobal) {
  501.                                 AutoAggregateSync();
  502.                                 if (AbsData == 0) {
  503.                                     long l;
  504.  
  505.                                     if (PIOpt) {            /*  must relocate period    */
  506.                                         l = AllocLabel();
  507.  
  508.                                         printf(
  509.                                             "x%ld\tdc.%c\t0\n"
  510.                                             "\tsection\tautoinit0,code\n"
  511.                                             "\tlea\t%s,A0\n",
  512.                                             l, SizC[actType->Size],
  513.                                             StorToString(&exp->ex_Stor, NULL)
  514.                                         );
  515.                                         if ((uword)AsmState == ASM_CODE) {
  516.                                             printf("\tlea\tx%ld(pc),A1\n", l);
  517.                                             printf("\tmove.%c\tA0,(A1)\n", SizC[actType->Size]);
  518.                                         } else {
  519.                                             printf("\tmove.%c\tA0,x%ld(A4)\n", SizC[actType->Size], l);
  520.                                         }
  521.                                         puts(LastSectBuf);
  522.                                     } else if (ResOpt && ((uword)AsmState == ASM_DATA || (uword)AsmState == ASM_BSS) && !(exp->ex_Stor.st_Flags & SF_CODE)) {
  523.                                         l = AllocLabel();
  524.  
  525.                                         printf(
  526.                                             "x%ld\tdc.%c\t0\n"
  527.                                             "\tsection\tautoinit0,code\n"
  528.                                             "\tlea\t%s,A0\n",
  529.                                             l, SizC[actType->Size],
  530.                                             StorToString(&exp->ex_Stor, NULL)
  531.                                         );
  532.                                         printf("\tmove.%c\tA0,x%ld", SizC[actType->Size], l);
  533.                                         if (SmallData == 2)
  534.                                             puts(".W");
  535.                                         else
  536.                                             puts("(A4)");
  537.                                         puts(LastSectBuf);
  538.                                     } else {
  539.                                         if ((uword)AsmState == ASM_CODE && ResOpt && !(exp->ex_Stor.st_Flags & SF_CODE))
  540.                                             zerror(EERROR_BADRELOC_IN_CONST);
  541.                                         goto skip;
  542.                                     }
  543.                                 } else {
  544. skip:
  545.                                     printf("\tdc.%c\t", SizC[actType->Size]);
  546.  
  547.                                     /*
  548.                                      *  must handle label, name indep.  Due to munging if data/code
  549.                                      */
  550.  
  551.  
  552.                                     if (exp->ex_Stor.st_Type == ST_RelLabel) {
  553.                                         if (exp->ex_Stor.st_Flags & SF_REGARGS)
  554.                                             putc('@', stdout);
  555.                                         printf("l%ld+%ld\n", exp->ex_Stor.st_Label, exp->ex_Stor.st_Offset);
  556.                                     } else if (exp->ex_Stor.st_Type == ST_RelName) {
  557.                                         printf("%c%.*s+%ld\n", (
  558.                                             (exp->ex_Stor.st_Flags & SF_REGARGS) ? '@' : '_'),
  559.                                             exp->ex_Stor.st_Name->Len,
  560.                                             exp->ex_Stor.st_Name->Name,
  561.                                             exp->ex_Stor.st_Offset
  562.                                         );
  563.                                     } else {
  564.                                         puts(StorToString(&exp->ex_Stor, NULL));
  565.                                     }
  566.                                 }
  567.                                 break;
  568.                             }
  569.                         default:
  570.                             /*
  571.                              *  For auto-aggregate generate the real offset
  572.                              *  for the instruction.  t.st_Offset holds the
  573.                              *  real base offset but does not include the
  574.                              *  relative base offset.
  575.                              */
  576.  
  577.                             if (GenGlobal == 0) {
  578.                                 t.st_Offset += baseOffset;
  579.                                 asm_getind(exp, TypeToPtrType(actType), &t, &c, -1, -1, 0);
  580.                                 asm_move(exp, &exp->ex_Stor, &c);
  581.                                 AutoAggregate(NULL, actType->Size);
  582.                                 t.st_Offset -= baseOffset;
  583.                             } else {
  584.                                 yerror(exp->ex_LexIdx, EERROR_NOT_LVALUE);
  585.                             }
  586.                             break;
  587.             }
  588.  
  589.             baseOffset += actType->Size;
  590.             }
  591.             FreeStorage(&exp->ex_Stor);
  592.         }
  593.         }
  594.     }
  595.  
  596.     /*
  597.      *  calculate bytes remaining then zero fill them (use baseOffset
  598.      *  as temporary)
  599.      */
  600.  
  601.     baseOffset = type->Size - baseOffset;
  602.  
  603.     if (baseOffset > 0) {
  604.         PadStructure(baseOffset, &bfhold);
  605.     } else if (baseOffset < 0) {
  606.         yerror((*pexp)->ex_LexIdx, EERROR_TOO_MANY_INITIALIZERS);
  607.     }
  608.     }
  609. }
  610.  
  611. void
  612. GenPercentEq(pexp)
  613. Exp **pexp;
  614. {
  615.     GenSpecialAssignment(pexp, GenPercent);
  616. }
  617.  
  618. void
  619. GenAndEq(pexp)
  620. Exp **pexp;
  621. {
  622.     GenSpecialAssignment(pexp, GenAnd);
  623. }
  624.  
  625. void
  626. GenStarEq(pexp)
  627. Exp **pexp;
  628. {
  629.     GenSpecialAssignment(pexp, GenStar);
  630. }
  631.  
  632. void
  633. GenMiEq(pexp)
  634. Exp **pexp;
  635. {
  636.     GenSpecialAssignment(pexp, GenMi);
  637. }
  638.  
  639. void
  640. GenDivEq(pexp)
  641. Exp **pexp;
  642. {
  643.     GenSpecialAssignment(pexp, GenDiv);
  644. }
  645.  
  646. void
  647. GenLtLtEq(pexp)
  648. Exp **pexp;
  649. {
  650.     GenSpecialAssignment(pexp, GenLShf);
  651. }
  652.  
  653. void
  654. GenGtGtEq(pexp)
  655. Exp **pexp;
  656. {
  657.     GenSpecialAssignment(pexp, GenRShf);
  658. }
  659.  
  660. void
  661. GenPlEq(pexp)
  662. Exp **pexp;
  663. {
  664.     GenSpecialAssignment(pexp, GenPl);
  665. }
  666.  
  667. void
  668. GenOrEq(pexp)
  669. Exp **pexp;
  670. {
  671.     GenSpecialAssignment(pexp, GenOr);
  672. }
  673.  
  674. void
  675. GenCaratEq(pexp)
  676. Exp **pexp;
  677. {
  678.     GenSpecialAssignment(pexp, GenXor);
  679. }
  680.  
  681. /*
  682.  *  handle special ass= expressions.  Setting the EF_ASSEQ flag will cause
  683.  *  structure bitfield refs to request EF_BFNOFREE, then use
  684.  *  CreateBinaryResult to copy the unfree storage.  bitfield += x; e.g.
  685.  */
  686.  
  687. void
  688. GenSpecialAssignment(pexp, genFunc)
  689. Exp **pexp;
  690. void (*genFunc)(Exp **);
  691. {
  692.     Exp *exp = *pexp;
  693.     long flags = exp->ex_Flags;
  694.  
  695.     exp->ex_Func = genFunc;
  696.     exp->ex_Flags |= EF_ASSEQ;
  697.     exp->ex_Flags &= ~EF_RNU;
  698.     exp->ex_ExpL->ex_Flags |= EF_LHSASSEQ;
  699.     (*exp->ex_Func)(pexp);
  700.     InsertNot(pexp);
  701.     exp = *pexp;
  702.     exp->ex_Func= GenAssEq;
  703.     exp->ex_Type = exp->ex_ExpL->ex_Type;
  704.     if (flags & EF_RNU)
  705.     exp->ex_Flags |= EF_RNU;
  706.     exp->ex_Flags |= EF_CRES;
  707. }
  708.  
  709. void
  710. GenAssEq(pexp)
  711. Exp **pexp;
  712. {
  713.     Exp *exp = *pexp;
  714.     Exp *e1;
  715.  
  716.     CallLeft();
  717.     e1 = exp->ex_ExpL;
  718.  
  719.     if (GenPass) {
  720.     if (e1->ex_ExpL->ex_Token == TokBFExt) {
  721.         FreeStorage(&e1->ex_ExpL->ex_ExpL->ex_Stor);
  722.         asm_bfsto(exp, &e1->ex_Stor, &e1->ex_ExpL->ex_ExpL->ex_Stor);
  723.     }
  724.     if (exp->ex_Flags & EF_RNU)
  725.         FreeStorage(&e1->ex_Stor);
  726.     else
  727.         exp->ex_Stor = e1->ex_Stor;
  728.     }
  729. }
  730.  
  731.